package main

import (
	"log/slog"
	"os"
	"time"

	"github.com/anthdm/hollywood/actor"
	"github.com/anthdm/hollywood/remote"

	"learn-go/hollywood/remote-benchmark/msg"
)

type client struct {
	serverPID *actor.PID
	count     int32
	beginTime time.Time
}

func newClient() actor.Receiver {
	return &client{
		serverPID: actor.NewPID("127.0.0.1:4000", "server/primary"),
	}
}

func (c *client) ping(ctx *actor.Context) {
	ctx.Send(c.serverPID, &msg.Ping{Count: c.count})
}

const pingTimes = 1000000

func (c *client) Receive(ctx *actor.Context) {
	switch m := ctx.Message().(type) {
	case actor.Started:
		slog.Info("client started")
		ctx.Send(c.serverPID, &msg.StartRemote{Sender: ctx.PID()})
	case *msg.Start:
		c.count = 1
		c.beginTime = time.Now()
		c.ping(ctx)
	case *msg.Pong:
		c.count = m.Count + 1
		if c.count%10000 == 0 {
			slog.Info("", "count=", c.count, "use time=", time.Since(c.beginTime))
		}
		if c.count >= pingTimes {
			useTime := time.Since(c.beginTime)
			qps := int(float32(pingTimes) / (float32(useTime) / float32(time.Second)))
			slog.Info("done", "count=", c.count, "qps=", qps)
			c.count = 1
			c.beginTime = time.Now()
		}
		c.ping(ctx)
	}
}

func main() {
	slog.SetDefault(slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelDebug})))
	r := remote.New("127.0.0.1:3000", remote.NewConfig())
	e, err := actor.NewEngine(actor.NewEngineConfig().WithRemote(r))
	if err != nil {
		panic(err)
	}

	e.Spawn(newClient, "client", actor.WithID("primary"))

	select {}
}
